#include <string>
#include <stdexcept>
#include <sstream>
#include <iomanip>

/**
 * @brief Assertion handling class
 * 
 * Provides assertion failure reporting functionality similar to the Fortran version.
 * When an assertion fails, it generates an error message with file and line information
 * and throws an exception to terminate program execution.
 */
class AssertionHandler {
public:
    /**
     * @brief Report an assertion failure
     * @param file The source file where assertion failed
     * @param line The line number where assertion failed
     * @throws std::runtime_error Always throws an exception with the assertion message
     * 
     */
    static void assertFailure(const std::string& file, int line) {
        std::ostringstream errorMessage;
        errorMessage << "Assertion failed at " << file << ":" 
                     << std::setw(4) << std::setfill('0') << line;
        
        throw std::runtime_error(errorMessage.str());
    }

    /**
     * @brief Macro wrapper for convenient assertion checking
     * 
     * Example usage:
     *   ASSERT(condition, "file.cpp", 42);
     * If condition is false, triggers assertFailure with file and line info.
     */
    #define ASSERT(cond, file, line) \
        if (!(cond)) { \
            AssertionHandler::assertFailure(file, line); \
        }
};

// Alternative modern C++17 version using source_location (if available)
#if __has_include(<experimental/source_location>)
#include <experimental/source_location>

class ModernAssertionHandler {
public:
    /**
     * @brief Reports assertion failure using C++20 source_location
     * @param condition The condition that failed
     * @param location Automatically captured source location
     * 
     * More modern approach that automatically captures file and line information.
     * Usage: MODERN_ASSERT(x > 0);
     */
    static void assertFailure(bool condition, 
                            const std::experimental::source_location& location = 
                            std::experimental::source_location::current()) {
        if (!condition) {
            std::ostringstream errorMessage;
            errorMessage << "Assertion failed at " << location.file_name() << ":" 
                         << location.line();
            
            throw std::runtime_error(errorMessage.str());
        }
    }
};

#define MODERN_ASSERT(cond) \
    ModernAssertionHandler::assertFailure((cond))
#endif